/* CS180 Project3 by Scott Wilkewitz and Matt Rodgers
 * swilkewi & rodgersm
 * 
 * Fully functioning game of checkers featuring kings and the ability to win.
 */

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Checkers extends JApplet implements ActionListener
{
  
  public static boolean runInApplet = true;
  public static Checkers game;
  static final long serialVersionUID = 0;
 
  //Window
  public JFrame frame;
  public JPanel topPanel, bottomPanel;
  public JLabel gameState, playerHoldings;
  public JButton newGameButton;
  
  //Game
  public Board board;
  boolean isBlackTurn;
  int numBlackPieces;
  int numRedPieces;
  
  //Pieces
  public Piece[] blackPieces = new Piece[12];
  public Piece[] redPieces = new Piece[12];
  public Piece[] highlights = new Piece[4];
  public Piece selectedPiece;
  
  
  //Startup
  public static void main(String[]args)
  {
    runInApplet = false;
    game = new Checkers();
  }
  
  public Checkers()
  {
    
    //Instantiate Window and Game
    createTopPanel();
    createBottomPanel();
    createBoard();
    createFrame();
    
    //Set Starting Game State
    startGame();
  }
  
  public void createTopPanel()
  {
    
    topPanel = new JPanel(new BorderLayout());
    
    Font tempFont = new Font("", Font.PLAIN, 30);
    JLabel tempLabel = new JLabel("Checkers");
    tempLabel.setFont(tempFont);
    
    gameState = new JLabel("Player 1s Turn");
    
    topPanel.add(tempLabel, BorderLayout.NORTH);
    topPanel.add(gameState, BorderLayout.SOUTH);
  }
  
  public void createBottomPanel()
  {
    
    bottomPanel = new JPanel(new BorderLayout());
    
    playerHoldings = new JLabel("Player 1 has 12 pieces. Player 2 has 12 pieces.");
    
    newGameButton = new JButton("New Game"); 
    newGameButton.addActionListener(this);
    
    bottomPanel.add(playerHoldings, BorderLayout.NORTH);
    bottomPanel.add(newGameButton, BorderLayout.SOUTH);
  }
  
  public void createBoard()
  {
    
    board = new Board();
    board.setLayout(null);
   
    //Instantiate Pieces
    for(int i = 0; i < 12; i++){
      
      blackPieces[i] = new Piece();
      blackPieces[i].addActionListener(this);
      board.add(blackPieces[i]);
        
      redPieces[i] = new Piece();
      redPieces[i].addActionListener(this);
      board.add(redPieces[i]);
    }
    
    //Instantiate Highlights
    for(int i = 0; i < 4; i++){
      
      highlights[i] = new Piece();
      highlights[i].addActionListener(this);
      board.add(highlights[i]);
    }
  }
  
  public void createFrame()
  {
    
    //Add Panels to this JApplet
    add(topPanel, BorderLayout.NORTH);
    add(board, BorderLayout.CENTER);
    add(bottomPanel, BorderLayout.SOUTH);
      
    //Create Frame if not run in Applet
    if(!Checkers.runInApplet){
      
      frame = new JFrame();
    
      frame.setSize(405, 550);
      frame.setResizable(false);
      
      frame.add(this);
      frame.setVisible(true);
    }
  }
  
  public void startGame()
  {
    
    //Clear Board
    for(int x = 0; x < 8; x++){
      for(int y = 0; y < 8; y++){
        board.setState(x, y, Board.EMPTY);
      }
    }
    
    //Set Highlights Up
    hideHighlights();
    
    //Set Pieces Up
    for(int i = 0; i < 12; i++){
      
      blackPieces[i].isKing = false;
      blackPieces[i].setPosition((i%4)*2 + 1 - (i/4)%2, (i/4));
      board.setState(blackPieces[i].x, blackPieces[i].y, Board.BLACK);
        
      redPieces[i].isKing = false;
      redPieces[i].setPosition((i%4)*2 + (i/4)%2, i/4 + 5);
      board.setState(redPieces[i].x, redPieces[i].y, Board.RED);
    }
    
    //Set Labels
    gameState.setText("Player 1s Turn");
    playerHoldings.setText("Player 1 has 12 pieces. Player 2 has 12 pieces.");
    
    //Set Game State
    isBlackTurn = true;
    numBlackPieces = 12;
    numRedPieces = 12;
  }
  
  
  //Game Events
  public void actionPerformed(ActionEvent e)
  {
    
    Object s=e.getSource();
    
    //Piece Button Pressed
    for(int i = 0; i < 12; i++){
      
      if((isBlackTurn && s.equals(blackPieces[i])) || (!isBlackTurn && s.equals(redPieces[i]))){
        selectPiece(i);
        return;
      }
    }
    
    //Highlight Button Pressed
    for(int i = 0; i < 4; i++){
      
      if(s.equals(highlights[i])){
        movePiece(highlights[i].x, highlights[i].y);
        return;
      }
    }
    
    //New Game Button Pressed
    if(s.equals(newGameButton)){
      startGame();
    }
  }
  
  
  //Game Logic
  public void selectPiece(int i)
  {
    
    hideHighlights();
    
    if(isBlackTurn)
      selectedPiece = blackPieces[i];
    else
      selectedPiece = redPieces[i];
    
    setHighlights();
  }
  
  public void hideHighlights()
  {
    
    for(int i = 0; i < 4; i++){
      
      if(highlights[i].isOnBoard() && board.getState(highlights[i].x, highlights[i].y) == Board.HIGHLIGHT){
         board.setState(highlights[i].x, highlights[i].y, Board.EMPTY);
      }
      
      highlights[i].setPosition(-1, -1);
    }
  }
  
  public void setHighlights()
  {
    
    if(isBlackTurn){
      
      //Set Standard Highlights
      setRelativeHighlights(0, -1, 1);
      setRelativeHighlights(1, 1, 1);
      
      //Set King's Highlights
      if(selectedPiece.isKing){
        setRelativeHighlights(2, -1, -1);
        setRelativeHighlights(3, 1, -1);
      }
      
    }else{
      
      //Set Standard Highlights
      setRelativeHighlights(0, -1, -1);
      setRelativeHighlights(1, 1, -1);
      
      //Set King's Highlights
      if(selectedPiece.isKing){
        setRelativeHighlights(2, -1, 1);
        setRelativeHighlights(3, 1, 1);
      }
    }
  }
  
  public void setRelativeHighlights(int index, int i, int j)
  {
    
    int[] state;
    
    state = getRelativeState(i, j);
    
    //Set Move Highlight
    if(state[0] == Board.EMPTY){
      highlights[index].setPosition(state[1], state[2]);
      board.setState(highlights[index].x, highlights[index].y, Board.HIGHLIGHT);
        
    }else if((isBlackTurn && (state[0] == Board.RED)) || (!isBlackTurn && (state[0] == Board.BLACK))){
        
      state = getRelativeState(i * 2, j * 2);
        
      //Set Jump Highlight
      if(state[0] == Board.EMPTY){
        highlights[index].setPosition(state[1], state[2]);
        board.setState(highlights[index].x, highlights[index].y, Board.HIGHLIGHT);
      }
    }
  }
  
  public int[] getRelativeState(int i, int j)
  {
    
    int[] state = new int[3];
    
    //Get Coordinates Relative to selectedPiece
    state[1] = selectedPiece.x + i;
    state[2] = selectedPiece.y + j;
    
    //Get State of Board at that Location
    if(0 <= state[1] && state[1] < 8 && 0 <= state[2] && state[2] < 8)
      state[0] = board.getState(state[1], state[2]);
    else
      state[0] = -1;
    
    return state;
  }
  
  public void movePiece(int x, int y)
  {
    
    //Update Label
    if(!isBlackTurn)
      gameState.setText("Player 1s Turn");
    else
      gameState.setText("Player 2s Turn");
    
    //Jump Piece
    if(Math.abs(selectedPiece.x - x) == 2){
      jumpPiece(x, y);
    }
   
    //Move Selected Piece
    board.setState(selectedPiece.x,selectedPiece.y,Board.EMPTY);
    selectedPiece.setPosition(x, y);
    
    //Update Board
    if(isBlackTurn){
      board.setState(x, y, Board.BLACK);
      
      if(selectedPiece.isKing)
        board.setState(x,y, Board.BLACK_KING);
      
    }else{
      board.setState(x, y, Board.RED);
      
      if(selectedPiece.isKing)
        board.setState(x,y, Board.RED_KING);
    }
    
    //King if on other side.
    if(isBlackTurn && y == 7){
         selectedPiece.isKing=true;
         board.setState(x, y, Board.BLACK_KING);
         
    }else if(!isBlackTurn && y == 0){
        selectedPiece.isKing=true;
        board.setState(x, y, Board.RED_KING);
    }
    
    //Switch Turns
    isBlackTurn = !isBlackTurn;
    
    //Remove Highlights
    hideHighlights();
  }
  
  public void jumpPiece(int x, int y)
  {
    
    //Get Coordinates of Jumped Piece
    int midX = (selectedPiece.x + x) / 2;
    int midY = (selectedPiece.y + y) / 2;
      
    //Find jumped piece
    Piece tempPiece = null;
    for(int i = 0; i < 12; i++){
        
      if(blackPieces[i].x == midX && blackPieces[i].y == midY){
        tempPiece = blackPieces[i];
        numBlackPieces--;
          
        //Check Red Win
        if(numBlackPieces == 0){
          gameState.setText("Red wins!");
          playerHoldings.setText("Start new game?");
        }
        break;
      }
        
      if(redPieces[i].x == midX && redPieces[i].y == midY){
        tempPiece = redPieces[i];
        numRedPieces--;
          
        //Check Black Win
        if(numRedPieces == 0){
          gameState.setText("Black wins!");
          playerHoldings.setText("Start new game?");
        }
        break;
      }
    }
      
    //Kill Piece
    board.setState(tempPiece.x, tempPiece.y, Board.EMPTY);
    tempPiece.setPosition(-1, -1);
      
    //Update Label
    if(numBlackPieces != 0 && numRedPieces != 0)
      playerHoldings.setText("Player 1 has " + numBlackPieces + " pieces. Player 2 has " + numRedPieces + " pieces.");
  }
}
